package com.authine.cloudpivot.ext.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.domain.query.GoodsInputQuery;
import com.authine.cloudpivot.ext.domain.query.GoodsQuery;
import com.authine.cloudpivot.ext.domain.query.MallQuery;
import com.authine.cloudpivot.ext.domain.vo.*;
import com.authine.cloudpivot.ext.domain.vo.order.OrderCustomerVO;
import com.authine.cloudpivot.ext.dto.GatewayResponse;
import com.authine.cloudpivot.ext.dto.Page;
import com.authine.cloudpivot.ext.dto.goods.VendorGoodsEntity;
import com.authine.cloudpivot.ext.dto.goods.VendorGoodsV1Entity;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.dto.system.UserDto;
import com.authine.cloudpivot.ext.entity.goods.GoodsFullEntity;
import com.authine.cloudpivot.ext.enums.commoditymaterials.GoodsPurchaseTypeEnum;
import com.authine.cloudpivot.ext.enums.goods.GoodsType;
import com.authine.cloudpivot.ext.enums.order.CartTypeEnum;
import com.authine.cloudpivot.ext.enums.system.RoleAdminEnum;
import com.authine.cloudpivot.ext.model.goods.GoodsFullModel;
import com.authine.cloudpivot.ext.service.ExternalInterfaceService;
import com.authine.cloudpivot.ext.service.GoodsService;
import com.authine.cloudpivot.ext.service.ICartService;
import com.authine.cloudpivot.ext.service.OrderService;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.cloudpivot.ext.utils.convert.BOConvert;
import com.authine.cloudpivot.ext.utils.system.OrgUtils;
import com.authine.cloudpivot.ext.utils.system.RoleUtils;
import com.authine.cloudpivot.ext.utils.system.SessionUser;
import com.authine.cloudpivot.ext.utils.system.UserUtils;
import com.authine.cloudpivot.metadata.design.dto.clientobject.domainmodel.schema.BizSchema;
import com.authine.cloudpivot.metadata.design.dto.clientobject.domainmodel.schema.Properties;
import com.authine.hermes.model.flow.enums.type.UnitType;
import com.authine.mvp.app.launcher.domain.gateway.appmeata.query.MetaQueryI;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
public class ExternalInterfaceServiceImpl implements ExternalInterfaceService {

    NamedParameterJdbcTemplate jdbcTemplate = ApplicationContextUtils.getBean(NamedParameterJdbcTemplate.class);

    MetaQueryI metaQueryI = ApplicationContextUtils.getBean(MetaQueryI.class);
    GoodsService goodsService = GoodsServiceImpl.getInstance();
    OrderService orderService = OrderServiceImpl.getInstance();
    ICartService iCartService = ICartServiceImpl.getInstance();

    private ExternalInterfaceServiceImpl() {
    }

    public static ExternalInterfaceServiceImpl getInstance() {
        return ExternalInterfaceServiceImplBuilder.instance;
    }

    /**
     * 查询企业采购单
     */
    @Override
    public List<GoodsPurchaseVO> queryPurchaseByQuotationIds(List<String> quotationIdList,
                                                             List<String> customerOrgIds,
                                                             List<String> vendorOrgIds,
                                                             List<String> inquiryMemberId) {

        StringBuilder selectSql = new StringBuilder("SELECT * from commoditymaterials.i_commoditymaterials_t_goods_purchase as purchase ")
                .append("LEFT JOIN  sourcingcenter.i_sourcingcenter_t_inquiry as inquiry on purchase.inquiry_id = inquiry.id ");

        String selectField = "purchase.id, purchase.type, JSON_UNQUOTE(purchase.customer_id -> '$.id') as customerId, JSON_UNQUOTE(purchase.vendor_id -> '$.id') as vendorId, purchase.quotation_goods_id, purchase.catalog , purchase.brand, purchase.name, purchase.model, purchase.spec, purchase.unit, purchase.package_unit, purchase.package_num, purchase.customer_sku, purchase.customer_bar_code, purchase.vendor_sku, purchase.vendor_bar_code, purchase.golden_tax, purchase.unspsc, purchase.delivery, purchase.num,purchase.pretax_price, purchase.price , purchase.pretax_total, purchase.total , purchase.tax_rate , purchase.tax_payable, purchase.pretax_freight, purchase.freight, purchase.tax_rate_freight, purchase.tax_payable_freight, purchase.pretax_amount, purchase.amount , purchase.images , purchase.price , purchase.expire , purchase.description , purchase.picketage_reason , purchase.picketage_time, purchase.bought , purchase.saled , purchase.enabled , purchase.vmi_goods as vmiGoods, JSON_UNQUOTE(purchase.customer_id -> '$.name') as customerName , JSON_UNQUOTE(purchase.vendor_id -> '$.name') as vendorName, DATEDIFF(now(), inquiry.expire) as expireTime , purchase.quote_total_strategy, purchase.inquiry_id";

        StringBuilder whereStr = new StringBuilder(" where purchase.enabled = 1 and purchase.deleted = 0  ");
        HashMap<String, Object> param = new HashMap<>();

        if (CollectionUtil.isNotEmpty(quotationIdList)) {
            whereStr.append("  and purchase.quotation_goods_id in (:quotation_goods_id) ");
            param.put("quotation_goods_id", quotationIdList);
        }
        if (CollectionUtil.isNotEmpty(vendorOrgIds)) {
            whereStr.append(" and  purchase.vendor_id in (:vendor_id) ");
            param.put("vendor_id", vendorOrgIds);
        }
        if (CollectionUtil.isNotEmpty(customerOrgIds)) {
            whereStr.append(" and purchase.customer_id in (:customer_id) ");
            param.put("customer_id", customerOrgIds);
        }

        if (CollectionUtil.isNotEmpty(inquiryMemberId)) {
            whereStr.append("  and inquiry.member_id in (:member_id) ");
            param.put("member_id", inquiryMemberId);
        }
        //组合sql
        int index = selectSql.indexOf("*");
        selectSql.replace(index, index + 1, selectField).append(whereStr);

        List<Map<String, Object>> maps = jdbcTemplate.queryForList(selectSql.toString(), param);

        log.info("maps={}", JSON.toJSONString(maps));

        List<GoodsPurchaseVO> list = jdbcTemplate.query(selectSql.toString(), param, BeanPropertyRowMapper.newInstance(GoodsPurchaseVO.class));

        Assert.isFalse(list.size() > SystemConstants.MAX_SIZE, "返回尺寸过大错误");

        return list;
    }

    @Override
    public Set<ShopVo> getShopVoByCompanyAndCustomerSku(Set<Map<String, Object>> goods) {

        UserDto user = UserUtils.getCurrentUser();

        Assert.isTrue(user != null, "获取用户信息失败");

        String orgId = null;
        if ("牧原食品股份有限公司".equals(user.getOrganization_name())) {
            orgId = user.getOrganization_id().get(0).getId();
        }
        //用于查询包含角色 "ROLE_CUSTOMER_COMPANY_REGION" 的用户，该用户用户维护牧原公司区域对照关系

        List<UserDto> userList = UserUtils.getOrganizationUserByRoleName(user.getId(), "ROLE_CUSTOMER_COMPANY_REGION");
        //过滤掉空值
        Set<Map<String, Object>> objects = goods.stream()
                .filter(a -> StringUtils.isNotEmpty((String) a.get("company")) && StringUtils.isNotEmpty((String) a.get("customerSku")))
                .collect(Collectors.toSet());
        //获取公司集合
        Set<String> companyList = objects.stream().map(a -> (String) a.get("company")).collect(Collectors.toSet());

        Set<Map<String, Object>> goodsPurchase = new HashSet<>();
        if (CollectionUtil.isNotEmpty(userList) && CollectionUtil.isNotEmpty(companyList)) {
            //获取收货地址集合
            List<Map<String, Object>> areaList = JdbcTemplateUtils.builder(AppConst.PERSONAL_CENTER, ModelConst.T_MEMBER_DELIVER_ADDRESS)
                    .selectField(" * ")
                    .eq("member_id -> '$.id'", userList.get(0).getId())
                    .in("alias", companyList)
                    .queryForList();

            if (areaList != null && areaList.size() > 0) {
                //增加查询条件,area
                for (Map<String, Object> goods1 : objects) {
                    for (Map<String, Object> area : areaList) {
                        if (area.get("alias").equals(goods1.get("company"))) {
                            goods1.put("area", area.get("post"));
                            goodsPurchase.add(goods1);
                            break;
                        }
                    }
                }
            }
        }

        if (goodsPurchase.isEmpty()) {
            return Collections.emptySet();
        }

        List<String> inquiryGoodsIds = JdbcTemplateUtils.builder(AppConst.SOURCING_CENTER, ModelConst.T_INQUIRY_GOODS)
                .selectField("id")
                .in("sku", goodsPurchase.stream().map(m -> m.get("customerSku")).collect(Collectors.toList()))
                .in("area", goodsPurchase.stream().map(m -> m.get("area")).collect(Collectors.toList()))
                .queryForList(String.class);

        if (inquiryGoodsIds.isEmpty()) {
            return Collections.emptySet();
        }

        String col = "id, quotation_goods_id as quotationId, picketage_reason , customer_sku , catalog, brand, name, model, spec, unit, package_num , package_unit , delivery, num, pretax_price , price, tax_rate , freight, pretax_freight t, tax_rate_freight , expire, description, createdTime , vendor_name , JSON_UNQUOTE(vendor_id -> '$.id') as vendorId, clarify_tips , maximum, cost_center_name,needAndAsk as source , area, company, warehouse, type, quote_total_strategy";

        List<ShopVo> list = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODS_PURCHASE)
                .selectField(col)
                .eq("saled", 1)
                .gt("expire", new Date())
                .in("inquiry_goods_id", inquiryGoodsIds)
                .queryForJavaBean(ShopVo.class);


        Assert.isFalse(list.size() > SystemConstants.MAX_SIZE, "返回尺寸过大错误");


        //todo 需要确认代码,以上根据客户代码逻辑写的, 最终获取数据只是通过 公司名称和customerSku,没有用户唯一确定属性参与查询

        return list.stream().collect(Collectors.toSet());
    }

    /**
     * 查询购物车列表
     *
     * @param type
     * @return
     */
    @Override
    public List<CartVo> getCartList(CartTypeEnum type) {

        List<CartVo> cartVos = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_CART)
                .selectField(" * ")
//                .eq("enabled", 1)
                .eq("member_id -> '$.id'", RequestContext.getCorpLoginId())
                .eq("type", type.getId())
                .desc("createdTime")
                .queryForJavaBean(CartVo.class);


        return cartVos;
    }

    /**
     * 根据条件查询采购目录
     */
    @Override
    public GatewayResponse<List<ShopVo>> shopGoodsPage(String customerSku, String brand, String catalog, String name,
                                                       String model, String spec, Integer type, Integer page, Integer pageSize) {

        Boolean roleJudge = false;
        GoodsPurchaseTypeEnum goodsPurchaseTypeEnum = null;
        if (null == type || type == 1) {
            goodsPurchaseTypeEnum = GoodsPurchaseTypeEnum.SINGLE;
            roleJudge = true;
        } else if (type == 0) {
            goodsPurchaseTypeEnum = GoodsPurchaseTypeEnum.ALL;
        } else if (type == 2) {
            goodsPurchaseTypeEnum = GoodsPurchaseTypeEnum.LOOP;
        } else {
            return GatewayResponse.failed("采购类型不正确！！ ");
        }

        SessionUser sessionUser = new SessionUser();

        String inquiryMemberId = null;
        List<String> customerIdList = null;
        if (!sessionUser.isPm()) {


//            customerIdList = UserUtils.listSubMemberIds(sessionUser.getCurrentUserId());
            customerIdList = OrgUtils.getOrgListByOrgId(sessionUser.getCurrentOrgID()).stream().map(OrganizationDto::getId).collect(Collectors.toList());

            if (roleJudge) {
                //获取当前登录ID
                inquiryMemberId = sessionUser.getCurrentUserId();

                //当前登录是否有管理员角色
                boolean b = RoleUtils.existByUserIdAndRoleName(sessionUser.getCurrentUserId(), RoleAdminEnum.ROLE_CUSTOMER_ADMIN.getName());
                // 当前登录人组织是否有管理员角色
                if (!b) {
                    b = RoleUtils.existByOrgIdAndRoleName(sessionUser.getCurrentUserId(), RoleAdminEnum.ROLE_CUSTOMER_ADMIN.getName());
                }
                //判断是否是部门管理员，如果是部门管理员询价人ID=null
                if (b) {
                    inquiryMemberId = null;
                }
            }
        }

        Map<String, Object> param = new HashMap<>();
        StringBuilder whereSql = new StringBuilder(JdbcTemplateUtils.getTableName(ModelConst.T_GOODS_PURCHASE, AppConst.COMMODITYMATERIALS))
                .append(" as goods left join ").append(JdbcTemplateUtils.getTableName(ModelConst.T_INQUIRY, AppConst.SOURCING_CENTER))
                .append(" as inquiry on goods.inquiry_id = inquiry.id  where goods.type = :type ");

        param.put("type", goodsPurchaseTypeEnum.getId());


        if (StringUtils.isNotEmpty(catalog)) {
            param.put("catalog", catalog);
            whereSql.append("and goods.catalog = :catalog ");
        }
        if (StringUtils.isNotEmpty(brand)) {
            param.put("brand", brand);
            whereSql.append("and goods.brand = :brand ");
        }
        if (StringUtils.isNotEmpty(name)) {
            param.put("name", "%".concat(name.trim()).concat("%"));
            whereSql.append("and goods.name like :name ");
        }
        if (StringUtils.isNotEmpty(model)) {
            param.put("model", model);
            whereSql.append("and goods.model = :model ");
        }
        if (StringUtils.isNotEmpty(spec)) {
            param.put("spec", spec);
            whereSql.append("and goods.spec = :spec ");
        }
        if (StringUtils.isNotEmpty(customerSku)) {
            param.put("customer_sku", customerSku);
            whereSql.append("and goods.customer_sku = :customer_sku ");
        }
        if (StringUtils.isNotEmpty(inquiryMemberId)) {
            param.put("member_id", inquiryMemberId);
            whereSql.append("and JSON_UNQUOTE(inquiry.member_id  -> '$.id') = :member_id ");
        }
        if (CollectionUtil.isNotEmpty(customerIdList)) {
            param.put("customer_id", customerIdList);
            whereSql.append("and JSON_UNQUOTE(goods.customer_id -> '$.id') in (:customer_id) ");
        }
        param.put("expire", new Date());
        whereSql.append("and goods.expire >= :expire ");
        log.info("===========param={}", param);
        //查询总数
        Integer count = jdbcTemplate.queryForObject(new StringBuilder("select  count(*) as count from ").append(whereSql).toString(), param, Integer.class);
        List<ShopVo> list;
        if (count == 0) {
            list = Collections.emptyList();
        } else {
            //排序和分页查询数据
            String limit = new Page(page, pageSize).limit();
            StringBuilder sql = new StringBuilder("select goods.* from ").append(whereSql).append(" order by createdTime desc  ").append(limit);
            BeanPropertyRowMapper<ShopVo> tBeanPropertyRowMapper = BeanPropertyRowMapper.newInstance(ShopVo.class, new BOConvert());
            list = jdbcTemplate.query(sql.toString(), param, tBeanPropertyRowMapper);
            if (CollectionUtils.isEmpty(list)) {
                list = Collections.emptyList();
            }
        }


        return GatewayResponse.<List<ShopVo>>builder().count(count).data(list).code(200).build();
    }

    private static void goodsDataCalculation(Map<String, Object> newGoods, Map<String, Object> oldGoods) {

        Object pretax_price = newGoods.get("pretax_price");
        Object price = newGoods.get("price");
        Object tax_rate = newGoods.get("tax_rate");

        // 税前单价,税后单价,税率都没修改,直接返回
        if (Objects.isNull(pretax_price) && Objects.isNull(price) && Objects.isNull(tax_rate)) {
            return;
        }

        BigDecimal pretaxPrice1;
        BigDecimal price1;
        BigDecimal taxRate1;

        if (Objects.isNull(pretax_price)) {
            pretaxPrice1 = new BigDecimal(oldGoods.get("pretax_price").toString());
        } else {
            pretaxPrice1 = new BigDecimal(pretax_price.toString());
        }

        if (Objects.isNull(price)) {
            price1 = new BigDecimal(oldGoods.get("price").toString());
        } else {
            price1 = new BigDecimal(price.toString());
        }

        if (Objects.isNull(tax_rate)) {
            taxRate1 = new BigDecimal(oldGoods.get("tax_rate").toString());
        } else {
            taxRate1 = new BigDecimal(tax_rate.toString());
        }

        //计算税后单价
        if (tax_rate != null || pretax_price != null) {
            price1 = BigDecimalUtils.round(BigDecimalUtils.mul(pretaxPrice1, taxRate1.add(BigDecimal.ONE)), 4);
        } else if (price != null) {
            // 计算税前
            pretaxPrice1 = BigDecimalUtils.round(BigDecimalUtils.div(price1, taxRate1.add(BigDecimal.ONE)), 4);
        }

        newGoods.put("pretax_price", pretaxPrice1);
        newGoods.put("price", price1);
        newGoods.put("tax_rate", taxRate1);
    }

    /**
     * 批量删除供应商商品
     *
     * @return
     */
    @Override
    public GatewayResponse vendorGoodsDelete(List<String> goodsIds, List<String> clientGoodsIds) {


        if (CollectionUtils.isNotEmpty(goodsIds)) {
            //删除条件, 商品id 和 组织id
            //1.先验证符合条件的数据是否存在
            List<String> list = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODSES)
                    .selectField(" id ")
                    .in("vendor_id -> '$.id'", new SessionUser().getCurrentOrgID())
                    .in("id", goodsIds)
                    .queryForList(String.class);

            if (CollectionUtil.isEmpty(list)) {
                return GatewayResponse.failed("商品不存在");
            }

            //是否匹配
            if (goodsIds.size() != list.size()) {
                return GatewayResponse.failed(String.format("商品%s不存在!", StringUtils.join(CollectionUtils.subtract(goodsIds, list), ",")));
            }
            //删除操作
            int id = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODSES)
                    .in("id", list)
                    .deleted();

        } else if (CollectionUtil.isNotEmpty(clientGoodsIds)) {
            SessionUser sessionUser = new SessionUser();

            //删除条件, client_goods_id , 客户端id, 组织id
            //1.先验证符合条件的数据是否存在
            List<Map<String, Object>> list = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODSES)
                    .selectField(" id,client_goods_id as clientGoodsId ")
                    .eq("vendor_id -> '$.id'", sessionUser.getCurrentOrgID())
                    .eq("client_id", sessionUser.get().getClient_id())
                    .in("client_goods_id", clientGoodsIds)
                    .queryForList();


            if (CollectionUtil.isEmpty(list)) {
                return GatewayResponse.failed("商品不存在");
            }

            //是否匹配
            if (clientGoodsIds.size() != list.size()) {
                Collection<String> subtract = CollectionUtils.subtract(goodsIds, list.stream().map(a -> (String) a.get("clientGoodsId")).collect(Collectors.toList()));
                return GatewayResponse.failed(String.format("商品%s不存在!", StringUtils.join(subtract, ",")));
            }
            //删除操作
            int id = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODSES)
                    .in("id", list.stream().map(a -> a.get("id")).collect(Collectors.toList()))
                    .deleted();

        } else {
            return GatewayResponse.failed("参数不能为空");
        }
        return GatewayResponse.failed("修改成功");
    }

    /**
     * 批量修改供应商商品
     * 批量修改成功后需要需要下架
     *
     * @param vendorGoodsList
     * @return
     */
    @Override
    public GatewayResponse toUpdateGoods(List<VendorGoodsVO> vendorGoodsList) {

        //存在goodsId 是空的数据
        boolean goodsIdNotFund = vendorGoodsList.stream().anyMatch(a -> Objects.isNull(a.getGoodsId()));
        //存在 clientGoodsId 是空的数据
        boolean clientGoodsIdNotFund = vendorGoodsList.stream().anyMatch(a -> Objects.isNull(a.getClientGoodsId()));
        //不能同时存在有一条 goodsId或 clientGoodsId 是空的数据
        if (goodsIdNotFund && clientGoodsIdNotFund) {
            return GatewayResponse.failed("未获取到部分商品的id, 请检查! ");
        }

        List<VendorGoodsEntity> oldList;
        if (!goodsIdNotFund) {
            //1.先验证符合条件的数据是否存在
            List<String> goodsIds = vendorGoodsList.stream().map(a -> String.valueOf(a.getGoodsId())).collect(Collectors.toList());
            oldList = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODSES)
                    .selectField(" * ")
                    .in("vendor_id -> '$.id'", new SessionUser().getCurrentOrgID())
                    .in("id", goodsIds)
                    .queryForJavaBean(VendorGoodsEntity.class);
            if (CollectionUtil.isEmpty(oldList)) {
                return GatewayResponse.failed("商品不存在");
            }

            if (oldList.size() != goodsIds.size()) {
                List<String> collect = oldList.stream().map(VendorGoodsEntity::getId).collect(Collectors.toList());
                return GatewayResponse.failed(String.format("未获取到商品:%s", StringUtils.join(CollectionUtils.subtract(goodsIds, collect), ",")));
            }

        } else {
            //1.先验证符合条件的数据是否存在
            List<String> clientGoodsIds = vendorGoodsList.stream().map(VendorGoodsVO::getClientGoodsId).collect(Collectors.toList());
            oldList = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODSES)
                    .selectField(" * ")
                    .eq("vendor_id -> '$.id'", new SessionUser().getCurrentOrgID())
                    .in("client_goods_id", clientGoodsIds)
                    .queryForJavaBean(VendorGoodsEntity.class);
            if (CollectionUtil.isEmpty(oldList)) {
                return GatewayResponse.failed("商品不存在");
            }

            if (clientGoodsIds.size() > oldList.size()) {
                List<String> collect = oldList.stream().map(VendorGoodsEntity::getClient_goods_id).collect(Collectors.toList());
                return GatewayResponse.failed(String.format("未获取到商品:%s", StringUtils.join(CollectionUtils.subtract(clientGoodsIds, collect), ",")));
            } else {
                // 把 id 补充到 goodsId
                for (VendorGoodsVO vgv : vendorGoodsList) {
                    for (VendorGoodsEntity vge : oldList) {
                        if (vgv.getClientGoodsId().equals(vge.getClient_goods_id())) {
                            vgv.setGoodsId(vge.getId());
                            break;
                        }
                    }
                }
            }
        }

        //VendorGoodsVO ->  VendorGoodsEntity
        List<VendorGoodsEntity> newList = vendorGoodsList.stream().map(VendorGoodsVO::vendorGoodsVoToGoodsEntity).collect(Collectors.toList());
        List<Map<String, Object>> newGoodsList = new ArrayList<>();
        List<Map<String, Object>> oldGoodsList = new ArrayList<>();
        goodCompare(newList, oldList, newGoodsList, oldGoodsList);

        if (newGoodsList.isEmpty()) {
            return GatewayResponse.failed("未识别到内容有修改,无需修改");
        }

        TransactionTemplate transactionTemplate = ApplicationContextUtils.getBean(TransactionTemplate.class);

        return transactionTemplate.execute(ts -> {

            SingleResponse<BO> boSingleResponse = BoServiceUtils.updateMainBo(ModelConst.T_GOODSES, newGoodsList);

            //修改成功后,历史记录表新增数据
            if (boSingleResponse.isSuccess()) {
                goodsService.addGoodsHistory(oldGoodsList);
            }
            return GatewayResponse.success("修改成功");
        });

    }

    /**
     * 分页查询供应商商品
     *
     * @param pageable
     * @param goodsQuery
     * @return
     */
    @Override
    public GatewayResponse<List<VendorGoodsV1VO>> pagedGoods(final Pageable pageable, final GoodsQuery goodsQuery) {

        SessionUser sessionUser = new SessionUser();

        JdbcTemplateUtils query = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODSES);


        if (goodsQuery.getGoodsId() != null) {
            query.eq("id", goodsQuery.getGoodsId());
        }

        if (StringUtils.isNotEmpty(goodsQuery.getClientGoodsId())) {
            query.eq("client_goods_id", goodsQuery.getClientGoodsId());
        }

        String vendorId = sessionUser.getCurrentOrgID();
        //判断是不是平台账号
        if (sessionUser.isPm()) {
            vendorId = null;
        }

        if (vendorId != null) {
            query.eq("vendor_id -> '$.id'", vendorId);
        }
        if (StringUtils.isNotEmpty(goodsQuery.getFilterName())) {
            query.like("name", goodsQuery.getFilterName());
        }
        if (StringUtils.isNotEmpty(goodsQuery.getBrand())) {
            query.like("brand", goodsQuery.getBrand());
        }
        if (StringUtils.isNotEmpty(goodsQuery.getModel())) {
            query.eq("model", goodsQuery.getModel());
        }
        if (StringUtils.isNotEmpty(goodsQuery.getSpec())) {
            query.eq("spec", goodsQuery.getSpec());
        }
        if (goodsQuery.getExpiry() != null) {
            query.gte("expiry", goodsQuery.getExpiry());
        }
        if (goodsQuery.getMinOrder() != null) {
            query.lte("min_order", goodsQuery.getMinOrder());
        }
        if (StringUtils.isNotEmpty(goodsQuery.getOrgFullName())) {
            query.like("org_fullname", goodsQuery.getOrgFullName());
        }
        if (goodsQuery.getStartTime() != null) {
            query.gte("createdTime", goodsQuery.getStartTime());
        }
        if (goodsQuery.getEndTime() != null) {
            query.lte("createdTime", goodsQuery.getEndTime());
        }
        List<Integer> type = Arrays.asList(GoodsType.Mall.ordinal(), GoodsType.Virtual.ordinal());
        query.in("type", type);

        Integer count = query.selectField(" count(*) ").queryForObject(Integer.class);

        List<VendorGoodsV1Entity> list = query.newField(" * ").page(pageable.getPageNumber(), pageable.getPageSize())
                .desc("id").queryForJavaBean(VendorGoodsV1Entity.class);


        List<VendorGoodsV1VO> dataList = VendorGoodsV1VO.listV1ToListV1Vo(list);

        return GatewayResponse.success(count, dataList);
    }

    @Override
    public GatewayResponse<List<GoodsFullModel>> pageMallGoodsByIds(String id, Boolean restrictedBrands) {
        GatewayResponse<List<GoodsFullEntity>> listGatewayResponse = goodsService.pageMallGoodsByIds(Collections.singletonList(id), true);
        List<GoodsFullModel> list = new ArrayList<>();
        if (listGatewayResponse.getCount() > 0) {
            list = listGatewayResponse.getData().stream().map(GoodsFullModel::entityToModel).collect(Collectors.toList());
            list.forEach(e -> e.setCalculatePrice(true));
        }
        return GatewayResponse.success(listGatewayResponse.getCount(), list);
    }

    @Override
    public GatewayResponse<MallGoodsVO> pageMallGoods(MallQuery query) {
        return goodsService.pageMallGoods(query);
    }

    /**
     * 批量保存供应商商品
     *
     * @param list
     * @return
     */
    @Override
    public GatewayResponse saveGoodsList(List<GoodsInputQuery> list) throws Exception {
        //非空验证
        if (list == null || list.isEmpty()) {
            return GatewayResponse.failed("供应商提交商品列表为空");
        } else if (list.size() > 1000) {
            return GatewayResponse.failed("导入数量不能大于1000条");
        }
        long l = System.currentTimeMillis();

        SessionUser sessionUser = new SessionUser();

        //平台导入
        Map<String, String> orgEntry = null;

        boolean isPmMember = sessionUser.isPm();
        if (isPmMember) {
            orgEntry = list.stream().map(goodsInputQuery -> {
                if (StringUtils.isEmpty(goodsInputQuery.getOrgFullname())) {
                    throw new BizException("组织名称不能为空");
                }
                OrganizationDto org = OrgUtils.getOrgByOrgName(goodsInputQuery.getOrgFullname());
                if (org == null) {
                    throw new BizException(String.format("组织: %s 不存在", goodsInputQuery.getName()));
                }
                return org;
            }).collect(Collectors.toMap(OrganizationDto::getName, OrganizationDto::getId, (k1, k2) -> k1));
        }

        //商品对象
        List<VendorGoodsEntity> addGoodsList = new ArrayList<>();
        List<VendorGoodsEntity> updateGoodsList = new ArrayList<>();
        //保存修改前的商品
        List<VendorGoodsEntity> updateBefore = new ArrayList<>();


        for (GoodsInputQuery g : list) {
            //判断同组织下是否有相同的物品，若果有覆盖原数据
            String orgId = sessionUser.getCurrentOrgID();
            if (isPmMember) {
                String importOrg = orgEntry.getOrDefault(g.getOrgFullname(), null);
                orgId = Optional.ofNullable(importOrg).orElse(orgId);
            }

            List<VendorGoodsEntity> vendorGoodsList = goodsService.queryEqualGoods(orgId, g.getName(), g.getBrand(), g.getModel(), g.getSpec(),
                    g.getUnit(), g.getPackageUnit(), new BigDecimal(g.getPackageNum()));


            if (vendorGoodsList.isEmpty()) {
                //新增
                VendorGoodsEntity createEntity = GoodsInputQuery.toVendorGoodsEntity(g);
                //平台导入
                if (isPmMember && MapUtils.isNotEmpty(orgEntry)) {
                    createEntity.setOrg_fullname(g.getOrgFullname());
                    createEntity.setVendor_id(Utils.createSelecorFormat(orgId, g.getOrgFullname(), UnitType.DEPARTMENT.getIndex()));

                }
                addGoodsList.add(createEntity);

            } else {
                VendorGoodsEntity goods = vendorGoodsList.get(0);

                if (goods != null) {
                    if (vendorGoodsList.size() > 1) {
                        log.warn("[goods-save] 商品:{},在库中有{}个重复", goods.getName(), vendorGoodsList.size());
                    }

                    VendorGoodsEntity update = GoodsInputQuery.toVendorGoodsEntity(g);
                    update.setId(goods.getId());

                    if (update.getPretax_price() != null || update.getTax_rate() != null) {
                        if (update.getPretax_price() == null) {
                            update.setPretax_price(goods.getPretax_price());
                        }
                        if (update.getTax_rate() == null) {
                            update.setTax_rate(goods.getTax_rate());
                        }
                        update.setPrice(BigDecimalUtils.round(BigDecimalUtils.mul(update.getPretax_price(), update.getTax_rate().add(BigDecimal.ONE)), 4));
                    }

                    //平台导入
                    if (isPmMember) {
                        update.setOrg_fullname(g.getOrgFullname());
                        update.setVendor_id(Utils.createSelecorFormat(orgId, g.getOrgFullname(), UnitType.DEPARTMENT.getIndex()));

                    }
                    updateBefore.add(goods);
                    updateGoodsList.add(update);
                }
            }
        }
        long l1 = System.currentTimeMillis();
        if (log.isDebugEnabled()) {
            log.debug("===============供应商商品批量导入 检查商品是否存在耗时：============" + (l1 - l));
        }


        //比较修改值是否一致,如果一致就不用再去修改
        List<Map<String, Object>> updateList = new ArrayList<>();
        List<Map<String, Object>> updateBeforeList = new ArrayList<>();
        goodCompare(updateGoodsList, updateBefore, updateList, updateBeforeList);

        //新增数据转换成map
        List<Map<String, Object>> addList = addGoodsList.stream().map(a -> JSON.parseObject(JSON.toJSONString(a, SerializerFeature.WriteMapNullValue))).collect(Collectors.toList());

        //批量保存商品
        boolean isOk = goodsService.insertAndUpdateList(addList, updateList);

        if (!isOk) {
            throw new BizException("操作失败");
        }

        if (!updateGoodsList.isEmpty()) {
            //todo 商品修改后 下架商城商品等 公共操作(通过队列)
        }
        if (log.isDebugEnabled()) {
            log.debug("================批量保存商品=================");
            log.debug(addGoodsList.toString() + "========= " + addGoodsList.size());
            log.debug("=================================");
            log.debug("================批量更新商品=================");
            log.debug(addGoodsList.toString() + "========= " + updateGoodsList.size());
            log.debug("=================================");
        }

        if (!updateBeforeList.isEmpty()) {
            long l6 = System.currentTimeMillis();
            goodsService.addGoodsHistory(updateBeforeList);
            long l7 = System.currentTimeMillis();
            if (log.isDebugEnabled()) {
                log.debug("===============商品批量导入  保存历史记录耗时============" + (l7 - l6) + "更新数量 :" + updateBeforeList.size());
            }
        }

        //上传数据大于100时邮件提醒供应商开发部
        int all = addList.size() + updateList.size();

        if (all > 100) {
            //todo 上传数据大于100时邮件提醒供应商开发部

        }

        return GatewayResponse.success("保存成功");
    }

    private void recoverCart(List<String> cartIds, boolean isClear) {
        if (isClear) {
            iCartService.recoverCart(cartIds);
            log.debug("恢复购物车商品 {}", cartIds);
        }
    }

    @Override
    public GatewayResponse createOrder(List<String> cartId) {


        OrderCustomerVO customerOrder = null;
        try {
            customerOrder = orderService.builderCustomerOrder(cartId);

        } catch (Exception e) {
            log.error("\n异常信息: {} \n 参数：[{}] \n 发生在: {}", e.getMessage(), cartId, e);
            return GatewayResponse.failed(e.getMessage());
        }
        if (customerOrder == null) {
            return GatewayResponse.failed("失败！");
        }

        boolean isClear = false;
        List<String> cartIds = customerOrder.getCartIds();
        try {
            isClear = iCartService.remove(cartIds);
            if (!isClear) {
                return GatewayResponse.failed("购物车商品扣减失败!");
            }

            OrderCustomerVO order = orderService.createOrder(customerOrder);

            // todo
//            applicationEventPublisher.publishEvent(new
//                    OrderRemoteSyncEvent(this, busProperties.getId(),
//                    "**", OrderRemoteSyncEventParam.builder().type(OrderSyncEventTypeEnum.OrderCreate).orderCustomerId(order.getId()).build()));
        } catch (BizException e) {
            recoverCart(cartIds, isClear);
            log.error("商城下单异常： {}  ", e.getMessage());
            return GatewayResponse.failed(e.getMessage());
        } catch (Exception e) {
            recoverCart(cartIds, isClear);
            log.error("商城下单异常： {} \n {} ", "confirmDirectOrder()", e.getMessage());
            return GatewayResponse.failed("订单处理错误:" + e.getMessage());
        } finally {
            if (!CollectionUtils.isEmpty(cartIds)) {
                // todo
//                applicationEventPublisher.publishEvent(new
//                        OrderRemoteSyncEvent(this, busProperties.getId(),
//                        "**", OrderRemoteSyncEventParam.builder().type(OrderSyncEventTypeEnum.RemoveCart).cartIds(cartIds).build()));
            }
        }
        return GatewayResponse.success("订单提交成功");
    }

    /**
     * 比较提交过来的字段值和原有值是否有不相等, 有不相等的对象才做后续修改
     *
     * @param newList
     * @param oldList
     */
    private void goodCompare(List<VendorGoodsEntity> newList, List<VendorGoodsEntity> oldList, List<Map<String, Object>> newGoodsList, List<Map<String, Object>> oldGoodsList) {
        //获取商品表的元数据
        BizSchema goodsMeta = metaQueryI.getBizSchemaByModel(ModelConst.T_GOODSES);
        List<Properties> properties = goodsMeta.getProperties();
        Map<String, VendorGoodsEntity> newMap = newList.stream().collect(Collectors.toMap(VendorGoodsEntity::getId, Function.identity()));
        Map<String, VendorGoodsEntity> oldMap = oldList.stream().collect(Collectors.toMap(VendorGoodsEntity::getId, Function.identity()));


        for (Map.Entry<String, VendorGoodsEntity> entry : newMap.entrySet()) {
            Map<String, Object> newGoods = JSON.parseObject(JSON.toJSONString(entry.getValue()));
            Map<String, Object> oldGoods = BeanUtil.beanToMap(oldMap.get(entry.getKey()));
            //获取到字段不相等
            boolean b = properties.stream().filter(p -> newGoods.containsKey(p.getCode()))
                    .anyMatch(p -> !BoUtils.BoFieldCompare(p, newGoods, oldGoods));

            if (b) {
                goodsDataCalculation(newGoods, oldGoods);
                newGoodsList.add(newGoods);
                oldGoodsList.add(oldGoods);
            }
        }
    }

    private static class ExternalInterfaceServiceImplBuilder {
        private static final ExternalInterfaceServiceImpl instance = new ExternalInterfaceServiceImpl();
    }

}
